<template>
    <div id="container" ref="container" style="width:100%;height:100%;" :style="{minHeight: isFromSQLQuery?monacoWrapperHeight:'300px'}"></div>
</template>
<script type="text/ecmascript-6">
import * as monaco from 'monaco-editor';
import { language as mysqlLanguage } from 'monaco-editor/esm/vs/basic-languages/mysql/mysql.js'
import { format } from 'sql-formatter'
export default {
    props:{
        btnDisabled:{
            type:Boolean,
            default:()=>false
        },
        editId:{
            type:String,
            default:()=>''
        },
        codes:{ // 编辑器中要回显的内容
            type:String,
            default:()=>''
        },
        readOnly: {
            type: Boolean,
            default:()=> false
        },
        language:{
            type:String,
            default:()=>'sql'
        },
        theme: {
            type: String,
            default:() => 'vs'
        },
        isMeta:{
            type:Boolean,
            default:() => false
        },
        // 编辑器的主要配置
        editorOptions:{
            type:Object,
            default:()=>{
                return {
                    selectOnLineNumbers: true,
                    roundedSelection: false,
                    readOnly: false,        // 只读
                    cursorStyle: 'line',        //光标样式
                    automaticLayout: true, //自动布局
                    glyphMargin: true,  //字形边缘
                    useTabStops: false,
                    fontSize: 12,       //字体大小
                    autoIndent:true,//自动布局
                }
            }
        },
        isFromSQLQuery: {
            type: Boolean,
            default: () => false
        },
        lineNumbers:{
            type:String,
            default: () => 'on'
        },
        monacoWrapperHeight:{
            type: String,
            default: () => ''
        },
        fixedOverflowWidgets: {
            type: Boolean,
            default: () => true
        },
        flowLake: {
            type: String,
            default: () => ''
        }
    },
    data() {
        return {
            showModal: false,
            monacoEditor: null,
            monacoEditorValue: '',
            monacoProvider: null,
            monacoHover: null,
            dbNameList: [],
            tableNameList: [],
            likeNameList: [],
            connectName: '',
            currentDbName: ''
        }
    },
    mounted() {
        this.initEditor();
        // this.getLibraryTableField(2)
        // this.getCurrentDbName()

        // 编辑器随窗口自适应
        // let resizeTimer = null
        // let self = this
        // window.addEventListener('resize', function () {
        //     console.log(111)
        //     if (resizeTimer) clearTimeout(resizeTimer)
        //     resizeTimer = setTimeout(function () {
        //         if (self.$refs.container) {
        //             self.initEditor()
        //         }
        //     }, 300)
        // })
    },
    beforeDestroy() {
        if (this.flowLake === 'sqlNode' && this.$route.path === '/DataFusionIde') {
            this.$emit('button2Click', '保存', null, {...this.$store.state.saveSqlParams, sqlContent:this.monacoEditorValue})
        }
    },
    destroyed() {
        this.monacoProvider && this.monacoProvider.dispose()
        this.monacoHover && this.monacoHover.dispose()
    },
    watch: {
        'monacoEditorValue'(value) {
           this.$emit('getMonacoEditValue', value);
        },
        'codes'(val){
            if(val==''){
                this.monacoEditorValue=""
            }else{
                this.monacoEditorValue=val
            }
            this.initEditor()
        },
        editId(val){
            if(val){
                this.monacoEditor.focus()
            }
        }
    },
    methods: {
        initEditor() {
            this.monacoProvider && this.monacoProvider.dispose()
            this.monacoHover && this.monacoHover.dispose()
            this.monacoEditor && this.monacoEditor.dispose();
            this.monacoEditor = monaco.editor.create(this.$refs.container, {
                lineNumbers: this.lineNumbers,
                value:this.monacoEditorValue || this.codes,
                language: this.language,
                theme: this.theme,//vs, hc-black, or vs-dark
                readOnly: this.readOnly,
                editorOptions:this.editorOptions,
                automaticLayout: true, // 是否自适应
                minimap: {
                    enabled: false   //是否开启小地图
                },
                lineHeight: 20,
                wordWrap: "on" ,  //单词换行，可以去除横向滚动条
                scrollBeyondLastLine: false,
                fixedOverflowWidgets: this.fixedOverflowWidgets, // 超出编辑器大小的使用 fixed 属性显示
                renderWhitespace: 'none',  //启用空白渲染。"all" | "none" | "boundary" | "selection"(默认) | "trailing"
                overviewRulerBorder: false, // 滚动条边框
                folding:false, //是否启用代码折叠(默认为true)  
                hideCursorInOverviewRuler:true, //滚动条上横向光标是否隐藏(true:隐藏，false:不隐藏)
                scrollbar: {
                    // Subtle shadows to the left & top. Defaults to true.
                    useShadows: false,
                    // Render vertical arrows. Defaults to false.
                    verticalHasArrows: true,
                    // Render horizontal arrows. Defaults to false.
                    // horizontalHasArrows: true,
                    // Render vertical scrollbar.
                    // Accepted values: 'auto', 'visible', 'hidden'.
                    // Defaults to 'auto'
                    vertical: 'auto',
                    verticalScrollbarSize: 17,
                    arrowSize: 20
                }
            });
            monaco.editor.defineTheme('myTheme', {
                base: 'vs',
                inherit: true,
                // rules: [{ background: 'EDF9FA' }],
                rules:[ //rules：高亮规则，即给代码里不同token类型的代码设置不同的显示样式，常见的token有string（字符串）、comment（注释）、keyword（关键词）等等。查找样式可以通过按F1或鼠标右键点击Command Palette，然后再找到并点击Developer: Inspect Tokens，接下来鼠标点哪一块代码，就会显示对应的信息，包括token类型，当前应用的颜色等。
                    { token: 'keyword.sql', foreground: '770088',fontStyle: 'bold' },
                    { token: 'operator.sql', foreground: '770088',fontStyle: 'bold' },
                    { token: 'string.sql', foreground: '9f251c' },
                    { token: 'comment.sql', foreground: 'aa5500' },
                    ],
                colors: {
                    'editorSuggestWidget.background':'#FFFFFF',  //联想输入框的背景
                    'editorSuggestWidget.border':'#CECED1',
                    'editor.lineHighlightBackground': '#fefae5', //点击某行高亮颜色
                    'editor.foreground': '#000000',
                    'editor.selectionBackground': '#7700882b', //选中背景
                    'editor.inactiveSelectionBackground': '#d9d9d9',
                    'textLink.activeForeground':'red'
                    // 'editorSuggestWidget.selectedBorder':'red',
                    // 'editorSuggestWidget.border':'#D8D8D8',
                    // 'editorSuggestWidget.highlightForeground':'red',  //联想输入框高亮字的颜色
                    // 'list.hoverBackground':'red',          //联想输入框的列的悬浮背景
                }
                });
            this.changeTheme('myTheme')
            // setTimeout(() => {
            //     this.monacoEditor.focus()
            // }, 300)
            if (this.flowLake === 'sqlNode' && this.$route.path === '/DataFusionIde') {
                this.monacoEditor.addAction({
                    id: 'my-save-id',
                    label: '保存',
                    keybindings: [
                        monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S,
                    ],
                    precondition: null,
                    keybindingContext: null,
                    contextMenuGroupId: '9_cutcopypaste',
                    contextMenuOrder: 1.5,
                    run:  (ed)=> {
                        this.$emit('button2Click', '保存')
                    }
                });
                this.monacoEditor.addAction({
                    id: 'my-run-id',
                    label: '运行',
                    keybindings: [
                        monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter,
                    ],
                    precondition: null,
                    keybindingContext: null,
                    contextMenuGroupId: '9_cutcopypaste',
                    contextMenuOrder: 1.5,
                    run:  (ed)=> {
                        this.$emit('button2Click', '运行')
                    }
                });
            }
            if (this.$parent.getDataBaseName) {
                this.monacoEditor.addAction({
                    id: '1', // 菜单项 id
                    label: '生成SQL', // 菜单项名称
                    contextMenuGroupId: '9_cutcopypaste', // 所属菜单的分组
                    run: () => {
                        // 点击后执行的操作
                        this.$parent.getDataBaseName()
                        this.$parent.createSqlModal = true
                    }
                })
                // this.monacoEditor.addAction({
                //     id: '2', // 菜单项 id
                //     label: '配置开发', // 菜单项名称
                //     contextMenuGroupId: '10_cutcopypaste', // 所属菜单的分组
                //     run: (e) => {
                //         this.$parent.$refs.config_dev.getHistoryTempt()
                //         this.$parent.$refs.config_dev.$refs.standard_template.getDataBaseName()
                //         this.$parent.$refs.config_dev.getFusionTempList()
                //         this.$parent.$refs.config_dev.configModal = true
                //     }
                // })
            }
            // if (this.$route.path === '/DataFusionIde') {
            //     // 运行选中/所有SQL
            //     this.monacoEditor.addAction({
            //         id: '3',
            //         label: '运行',
            //         contextMenuGroupId: '9_cutcopypaste',
            //         run: () => {
            //             console.log(this.getSelectedSql())
            //             this.$emit('button2Click', '运行', this.getSelectedSql())
            //         }
            //     })
            // }

            if(!this.monacoEditorValue && this.codes) {
                this.monacoEditorValue = this.codes
            }
            this.monacoEditor.onDidChangeModelContent((event) =>{ //编辑器内容changge事件
                this.monacoEditorValue = this.monacoEditor.getValue();
            });
            this.monacoEditor.onDidFocusEditorText(e => {   // 编辑器聚焦事件
                this.$emit('focus')
            })

            // 缓存表名
            this.monacoEditor.onKeyDown(event => {
                if (event.browserEvent.key == 'Enter') {
                    if (!document.getElementsByClassName('monaco-list-rows')[0].innerHTML) return
                    let typeFocus = document.getElementsByClassName('monaco-list-rows')[0].getElementsByClassName('focused')[0].getElementsByClassName('details-label')[0].innerText
                    let valFocus = document.getElementsByClassName('monaco-list-rows')[0].getElementsByClassName('focused')[0].getAttribute('aria-label')
                    // if (typeFocus == '<表>') {
                    if (typeFocus == this.currentDbName) {
                        let likeFlag = true
                        let arrTem = []
                        arrTem = window.sessionStorage.getItem('tableName') ? JSON.parse(window.sessionStorage.getItem('tableName')) : []
                        this.tableNameList.map(v => {
                            if (v.label == valFocus) {
                                likeFlag = false
                                arrTem.push(v)
                                return window.sessionStorage.setItem('tableName', JSON.stringify(arrTem))
                            }
                        })
                        if (likeFlag) {
                            this.likeNameList.map(v => {
                                if (v.label == valFocus) {
                                    arrTem.push(v)
                                    return window.sessionStorage.setItem('tableName', JSON.stringify(arrTem))
                                }
                            })
                        }
                    }
                }
            })

            // 设置编辑器语言
            this.monacoProvider = monaco.languages.registerCompletionItemProvider(
                this.language,
                {
                    triggerCharacters: ['$', '.', '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
                    provideCompletionItems: (model, position) => this.provideCompletionItems(model, position)
                }
            )

            this.monacoHover = monaco.languages.registerHoverProvider(
                this.language,
                {
                    provideHover: (model, position, token) => {
                        // position.lineNumber 当前所在行数
                        // model.getLineMinColumn(position.lineNumber) 光标最小值
                        // model.getLineMaxColumn(position.lineNumber) 光标最大值
                        if (!model.getWordAtPosition(position)) return
                        return {
                            // range: monaco.Range.fromPositions(
                            //     // model.getPositionAt(cursorInfo.token.position[0]),
                            //     // model.getPositionAt(cursorInfo.token.position[1] + 1)
                            // ),
                            // contents: [            // 悬浮的内容,可以有很多项
                            //     { value: '提示信息' },
                            //     { value: model.getWordAtPosition(position).word }
                            // ]
                        }
                    }
                }
            )

        },
        changeTheme(theme) {
            monaco.editor.setTheme(theme);
        },
        changeMonacoEditorValue(value) {
           this.monacoEditor.setValue(value);
        },
        close() {
           this.$Modal.remove();
        },
        insertMonacoEditorValue (value) {
            let selection = this.monacoEditor.getSelection()
            let range = new monaco.Range(selection.startLineNumber, selection.startColumn, selection.endLineNumber, selection.endColumn)
            let id = { major: 1, minor: 1 }
            let op = { identifier: id, range: range, text: value, forceMoveMarkers: true }
            this.monacoEditor.executeEdits('', [op])
            this.monacoEditor.focus()
        },
        async provideCompletionItems(model, position) {
            
            if (this.$route.path != '/DataFusionIde') {
                return {
                    suggestions: await this.getKeywordSuggest()
                }
            }
            // 光标位置
            const { lineNumber, column } = position
            // 当前行光标前文本
            const textBeforePointer = model.getValueInRange({
                startLineNumber: lineNumber,
                startColumn: 0,
                endLineNumber: lineNumber,
                endColumn: column
            })
            // 光标前文本
            const textBeforePointerMulti = model.getValueInRange({
                startLineNumber: 1,
                startColumn: 0,
                endLineNumber: lineNumber,
                endColumn: column
            })
            // 当前行光标后文本
            // const textAfterPointer = model.getValueInRange({
            //   startLineNumber: lineNumber,
            //   startColumn: column,
            //   endLineNumber: lineNumber,
            //   endColumn: model.getLineMaxColumn(model.getLineCount())
            // })
            // 光标后文本
            const textAfterPointerMulti = model.getValueInRange({
                startLineNumber: lineNumber,
                startColumn: column,
                endLineNumber: model.getLineCount(),
                endColumn: model.getLineMaxColumn(model.getLineCount())
            })
            // 当输入点的时候获取光标前的关键字
            const strTem = textBeforePointer.trim().endsWith('.') ? textBeforePointer.trim().split(/\s+|\.|\,|\=/).slice(-2)[0] : textBeforePointer.trim().split(/\s+|\.|,/).pop()
            const strBeforeSpace = textBeforePointer.trim().endsWith('.') ? textBeforePointer.trim().split(/\s+|\,|\=/)[textBeforePointer.trim().split(/\s+|\,|\=/).length - 1].substring(0, textBeforePointer.trim().split(/\s+|\,|\=/)[textBeforePointer.trim().split(/\s+|\,|\=/).length - 1].lastIndexOf('.')) : textBeforePointer.trim().split(/\s+|\.|,/).pop()
            //当输入$的时候获取光标前的关键字
            // const strBeforeSpace$ = textBeforePointer.trim().endsWith('$') ? textBeforePointer.trim().split(/\s+|\$|\=/).slice(-2)[0] : textBeforePointer.trim().split(/\s+|\$|\=/).pop()
            const strBeforeSpace$ = textBeforePointer.trim().split(/\$/)[textBeforePointer.trim().split(/\$/).length-1]
            console.log(textBeforePointer.trim().split(/\$/)[textBeforePointer.trim().split(/\$/).length-1],strBeforeSpace$)
            //'.'的时候表别名联想的前后sql
            const beforeSQL = textBeforePointerMulti.split(';')[textBeforePointerMulti.split(';').length - 1]
            const  afterSQL = textAfterPointerMulti.split(';')[0]
            //光标到最近一个（空格，',','='）分割的字符
            const lastString = textBeforePointer.trim().split(/\s+|\,|\=/)[textBeforePointer.trim().split(/\s+|\,|\=/).length - 1]
            //光标到最后一个空格分隔的字符
            const lastStringK = textBeforePointer.trim().split(/\s+/)[textBeforePointer.trim().split(/\s+/).length - 1]
            // 当输入点时，获取点之前的 [\w_]+ 字符串
            // const strBeforeSpace = textBeforePointer.trim().endsWith('.') ? (textBeforePointer.trim().match(/[\w_]+/g) ? textBeforePointer.trim().match(/[\w_]+/g)[textBeforePointer.trim().match(/[\w_]+/g).length - 1] : '') : textBeforePointer.trim().split(/\s+|\.|,/).pop()
            if (textBeforePointer.trim().endsWith('.')) {
                // 光标前面的内容（一直到分号前）
                let currentSqlBefore = textBeforePointerMulti.split(';')[textBeforePointerMulti.split(';').length - 1]
                // 光标后面的内容（一直到分号前）
                let currentSqlAfter = textAfterPointerMulti.split(';')[0]
                let currentSql = currentSqlBefore + currentSqlAfter
                // if (this.getTableNameAndTableAlia(currentSql).length && this.getTableNameAndTableAlia(currentSql).filter(item => item.tableAlia && item.tableAlia.toUpperCase() === strTem.toUpperCase()).length) {
                //     let currentAliasObj = this.getTableNameAndTableAlia(currentSql).filter(item => item.tableAlia.toUpperCase() === strTem.toUpperCase())[0]
                //     return {
                //         suggestions: await this.getLibraryTableField(5, '', currentAliasObj.tableName, '', currentAliasObj.dbName)
                //     }
                // } else {
                    return {
                        suggestions: [...await this.getLibraryTableField(7, '',{beforeSQL,afterSQL}, this.connectName)]
                    }
                // }
            } 
            else if(lastStringK.indexOf('$')!==-1){
                        return {
                            suggestions: [...await this.getLibraryTableField(8, '', strBeforeSpace$, this.connectName)]
                        }
                }
            else {
                if(lastString.indexOf('.')!=-1){
                    return {
                        suggestions: [...await this.getLibraryTableField(7, '',{beforeSQL,afterSQL}, this.connectName)]
                    }
                }else{
                    if (strBeforeSpace.length >= 3) {
                        return {
                            suggestions: [...this.getKeywordSuggest(), ...await this.getLibraryTableField(6, '', strBeforeSpace, this.connectName)]
                        }
                    } else {
                            return {
                                suggestions: [...this.getKeywordSuggest()]
                            }
                    }
                }
            }
            // 提取库名
            let dbName = textBeforePointer.trim().endsWith('.') && textBeforePointer.trim().split(/\s+|\.|\,|\=/).length > 2 ? textBeforePointer.trim().split(/\s+|\.|\,|\=/).slice(-3)[0] : ''
            dbName = this.dbNameList.filter(item => item.label === dbName).length ? this.dbNameList.filter(item => item.label === dbName)[0].label : ''
            // 判断点前面是否是库名
            let dataBaseFlag = false
            let dataBasePid = ''
            this.dbNameList.map(v => {
                if (v.label.toUpperCase() == strTem.toUpperCase()) {
                    dataBaseFlag = true
                    dataBasePid = v.pid
                }
            })
            // 判断点前面是否是表名
            let tableFlag = false
            let tablePid = ''
            if (window.sessionStorage.getItem('tableName') && JSON.parse(window.sessionStorage.getItem('tableName')).length > 0) {
                JSON.parse(window.sessionStorage.getItem('tableName')).map(v => {
                    if (v.label == strTem) {
                        tableFlag = true
                        tablePid = v.pid
                    }
                })
            }
            if (dataBaseFlag) {
                return {
                    suggestions: await this.getLibraryTableField(4, dataBasePid, strTem, this.connectName)
                }
            } else if (tableFlag) {
                return {
                    suggestions: await this.getLibraryTableField(5, tablePid, strTem, this.connectName, dbName)
                }
            } else {
                let currentSqlBefore = textBeforePointerMulti.split(';')[textBeforePointerMulti.split(';').length - 1]
                let currentSqlAfter = textAfterPointerMulti.split(';')[0]
                let currentSql = currentSqlBefore + currentSqlAfter
                let parenthesesLeft = currentSqlBefore.match(/(\(|\))/ig) ? currentSqlBefore.match(/(\(|\))/ig).pop() : ''
                let parenthesesRight = currentSqlAfter.match(/(\(|\))/ig) ? currentSqlAfter.match(/(\(|\))/ig)[0] : ''
                if ((parenthesesLeft == '(' && parenthesesRight == ')') || (!parenthesesLeft && !parenthesesRight)) {
                    if (parenthesesLeft == '(' && parenthesesRight == ')') {
                        let currentParenthesesContent = currentSqlBefore.split('(')[currentSqlBefore.split('(').length - 1] + currentSqlAfter.split(')')[0]
                        // console.log(this.getTableNameAndTableAlia(currentParenthesesContent))

                        if (this.getTableNameAndTableAlia(currentParenthesesContent).find(item => item.tableAlia == strTem)) {
                            let tablePid = ''
                            let tableName = ''
                            let dbName = ''
                            if (window.sessionStorage.getItem('tableName') && JSON.parse(window.sessionStorage.getItem('tableName')).length > 0) {
                                JSON.parse(window.sessionStorage.getItem('tableName')).map(v => {
                                    if (v.label == this.getTableNameAndTableAlia(currentParenthesesContent).find(item => item.tableAlia == strTem).tableName) {
                                        tablePid = v.pid
                                    }
                                })
                            }
                            this.getTableNameAndTableAlia(currentParenthesesContent).map(item => {
                                if (item.tableAlia == strTem) {
                                    tableName = item.tableName
                                    dbName = item.dbName
                                }
                            })
                            return {
                                suggestions: await this.getLibraryTableField(5, tablePid, tableName, this.connectName, dbName)
                            }
                        }

                    } else if (!parenthesesLeft && !parenthesesRight) {
                        // console.log(this.getTableNameAndTableAlia(currentSql))

                        // if (this.getTableNameAndTableAlia(currentSql).length == 0) {

                        // }

                        if (this.getTableNameAndTableAlia(currentSql).find(item => item.tableAlia == strTem)) {
                            let tablePid = ''
                            let tableName = ''
                            let dbName = ''
                            if (window.sessionStorage.getItem('tableName') && JSON.parse(window.sessionStorage.getItem('tableName')).length > 0) {
                                JSON.parse(window.sessionStorage.getItem('tableName')).map(v => {
                                    if (v.label == this.getTableNameAndTableAlia(currentSql).find(item => item.tableAlia == strTem).tableName) {
                                        tablePid = v.pid
                                    }
                                })
                            }
                            this.getTableNameAndTableAlia(currentSql).map(item => {
                                if (item.tableAlia == strTem) {
                                    tableName = item.tableName
                                    dbName = item.dbName
                                }
                            })
                            return {
                                // suggestions: await this.getLibraryTableField(5, tablePid)
                                // suggestions: await this.getLibraryTableField(5, tablePid, tableName, this.connectName)
                                // suggestions: [...this.getKeywordSuggest(), ...await this.getLibraryTableField(5, tablePid, tableName, this.connectName)]
                                suggestions: [...await this.getLibraryTableField(5, tablePid, tableName, this.connectName, dbName)]
                            }
                        }

                    }
                } else {
                    if (!parenthesesLeft || !parenthesesRight) {

                        // 子查询的别名
                        let currentSubqueryAliasTem = currentSql.match(/\)\s+[^\s+]+\,?/ig)
                        let currentSubqueryAlias = currentSubqueryAliasTem.map(v => {
                            return v.replace(/\)\s+/, '').replace(/\,/, '')
                        })
                        // 子查询的字段
                        let currentSubqueryFieldTem = currentSql.match(/\(\s+select[\s+a-zA-Z0-9\,\.\_]+from/ig) ? currentSql.match(/\(\s+select[\s+a-zA-Z0-9\,\.\_]+from/ig) : []
                        let currentSubqueryFieldStr = currentSubqueryFieldTem.map(v => {
                            return v.replace(/\(\s*select\s+/ig, '').replace(/\s+from/ig, '')
                        })
                        let currentSubqueryFieldNameTem = currentSubqueryFieldStr.map(v => {
                            return v.split(',').map(v => {
                                return v.split('.')[v.split('.').length - 1].trim()
                            })
                        })
                        currentSubqueryFieldNameTem = currentSubqueryFieldNameTem.reverse()
                        let currentSubqueryFieldName = currentSubqueryAlias.map((v, i) => ({fieldName: currentSubqueryFieldNameTem[i] ? currentSubqueryFieldNameTem[i] : [] , fieldAlia: v}))
                        // console.log(currentSubqueryAlias)
                        // console.log(currentSubqueryFieldNameTem)
                        // 别名和表名
                        // let currentTableNameAndTableAliaTem = currentSql.match(/(from|\,)\s*[a-zA-Z0-9\_\s\,]*(\,|where|left|right|full|join|inner|union)/ig)
                        let currentTableNameAndTableAliaTem = currentSql.match(/(from|\,)\s*[a-zA-Z0-9\_\s\,]*([^\s]|\,|(where|left|right|full|join|inner|union))/ig)
                        let currentTableNameAndTableAliaStr = currentTableNameAndTableAliaTem.map(v => {
                            return v.replace(/.*[\w\W]*from\s+/ig, '').replace(/\s+(where|left|right|full|join|inner|union).*/ig, '').replace(/^(\,\s*)/, '').replace(/(\s*\,)$/, '').replace(/\,\s+\(/, '').replace('(', '').replace(/[\w\W]*\.[\w\W]*/ig, '').replace(/\s*\)/ig, '')
                        })
                        let currentTableNameAndTableAliaArr = currentTableNameAndTableAliaStr.filter(v => {
                            return v && v.trim()
                        })
                        let currentTableNameAndTableAlia = []
                        currentTableNameAndTableAliaArr.map(v => {
                            v.split(/\s*\,\s*/ig).map(v => {
                                if (v.replace(/\s+as\s+/ig, ' ').split(' ').length === 2) {
                                    currentTableNameAndTableAlia.push({
                                        tableName: v.replace(/\s+as\s+/ig, ' ').split(' ')[0],
                                        tableAlia: v.replace(/\s+as\s+/ig, ' ').split(' ')[1]
                                    })
                                }
                            })
                        })
                        if (currentSubqueryFieldName.find(item => item.fieldAlia == strTem)) {
                            return {
                                suggestions: currentSubqueryFieldName.find(item => item.fieldAlia == strTem).fieldName.map(v => {
                                    return {
                                        label: v,
                                        kind: monaco.languages.CompletionItemKind.Function,
                                        insertText: v,
                                        detail: '<字段>'
                                    }
                                })
                            }
                        } else if (currentTableNameAndTableAlia.find(item => item.tableAlia == strTem)) {
                            let tablePid = ''
                            let tableName = ''
                            if (window.sessionStorage.getItem('tableName') && JSON.parse(window.sessionStorage.getItem('tableName')).length > 0) {
                                JSON.parse(window.sessionStorage.getItem('tableName')).map(v => {
                                    if (v.label == currentTableNameAndTableAlia.find(item => item.tableAlia == strTem).tableName) {
                                        tablePid = v.pid
                                    }
                                })
                            }
                            currentTableNameAndTableAlia.map(item => {
                                if (item.tableAlia == strTem) {
                                    tableName = item.tableName
                                }
                            })
                            return {
                                suggestions: await this.getLibraryTableField(5, tablePid, tableName, this.connectName)
                            }
                        }

                    } else {
                        if (parenthesesLeft == '(') {
                            // 获取括号作用域
                            let currentParenthesesGroupBefore = currentSqlBefore.split('(')[currentSqlBefore.split('(').length - 1]
                            let currentParenthesesSplitAfter = currentSqlAfter.split(')')
                            let currentParenthesesGroupAfter = ''
                            if (currentSqlAfter.match(/\(|\)/ig)[2] == ')') {
                                currentParenthesesGroupAfter = currentParenthesesSplitAfter.slice(0, 2).join(')')
                            } else if (currentSqlAfter.match(/\(|\)/ig)[4] == ')') {
                                currentParenthesesGroupAfter = currentParenthesesSplitAfter.slice(0, 3).join(')')
                            } else if (currentSqlAfter.match(/\(|\)/ig)[6] == ')') {
                                currentParenthesesGroupAfter = currentParenthesesSplitAfter.slice(0, 4).join(')')
                            }
                            let currentParenthesesGroup = currentParenthesesGroupBefore + currentParenthesesGroupAfter

                            // 子查询的别名
                            let currentSubqueryAliasTem = currentParenthesesGroup.match(/\)\s+[^\s+]+\,?/ig)
                            let currentSubqueryAlias = currentSubqueryAliasTem.map(v => {
                                return v.replace(/\)\s+/, '').replace(/\,/, '')
                            })
                            // 子查询的字段
                            let currentSubqueryFieldTem = currentParenthesesGroup.match(/\(\s+select[\s+a-zA-Z0-9\,\.\_]+from/ig)
                            let currentSubqueryFieldStr = currentSubqueryFieldTem.map(v => {
                                return v.replace(/\(\s*select\s+/ig, '').replace(/\s+from/ig, '')
                            })
                            let currentSubqueryFieldNameTem = currentSubqueryFieldStr.map(v => {
                                return v.split(',').map(v => {
                                    return v.split('.')[v.split('.').length - 1]
                                })
                            })
                            let currentSubqueryFieldName = currentSubqueryAlias.map((v, i) => ({fieldName: currentSubqueryFieldNameTem[i], fieldAlia: v}))
                            // 别名和表名
                            // let currentTableNameAndTableAliaTem = currentParenthesesGroup.match(/(from|\,)\s*[a-zA-Z0-9\_\s\,]*(\,|where|left|right|full|join|inner|union)/ig)
                            let currentTableNameAndTableAliaTem = currentParenthesesGroup.match(/(from|\,)\s*[a-zA-Z0-9\_\s\,]*([^\s]|\,|(where|left|right|full|join|inner|union))/ig)
                            let currentTableNameAndTableAliaStr = currentTableNameAndTableAliaTem.map(v => {
                                return v.replace(/.*[\w\W]*from\s+/ig, '').replace(/\s+(where|left|right|full|join|inner|union).*/ig, '').replace(/^(\,\s*)/, '').replace(/(\s*\,)$/, '').replace(/\,\s+\(/, '').replace('(', '').replace(/[\w\W]*\.[\w\W]*/ig, '').replace(/\s*\)/ig, '')
                            })
                            let currentTableNameAndTableAliaArr = currentTableNameAndTableAliaStr.filter(v => {
                                return v && v.trim()
                            })
                            let currentTableNameAndTableAlia = []
                            currentTableNameAndTableAliaArr.map(v => {
                                v.split(/\s*\,\s*/ig).map(v => {
                                    if (v.replace(/\s+as\s+/ig, ' ').split(' ').length === 2) {
                                        currentTableNameAndTableAlia.push({
                                            tableName: v.replace(/\s+as\s+/ig, ' ').split(' ')[0],
                                            tableAlia: v.replace(/\s+as\s+/ig, ' ').split(' ')[1]
                                        })
                                    }
                                })
                            })
                            if (currentSubqueryFieldName.find(item => item.fieldAlia == strTem)) {
                                return {
                                    suggestions: currentSubqueryFieldName.find(item => item.fieldAlia == strTem).fieldName.map(v => {
                                        return {
                                            label: v,
                                            kind: monaco.languages.CompletionItemKind.Function,
                                            insertText: v,
                                            detail: '<字段>'
                                        }
                                    })
                                }
                            } else if (currentTableNameAndTableAlia.find(item => item.tableAlia == strTem)) {
                                let tablePid = ''
                                let tableName = ''
                                if (window.sessionStorage.getItem('tableName') && JSON.parse(window.sessionStorage.getItem('tableName')).length > 0) {
                                    JSON.parse(window.sessionStorage.getItem('tableName')).map(v => {
                                        if (v.label == currentTableNameAndTableAlia.find(item => item.tableAlia == strTem).tableName) {
                                            tablePid = v.pid
                                        }
                                    })
                                }
                                currentTableNameAndTableAlia.map(item => {
                                    if (item.tableAlia == strTem) {
                                        tableName = item.tableName
                                    }
                                })
                                return {
                                    suggestions: await this.getLibraryTableField(5, tablePid, tableName, this.connectName)
                                }
                            }

                        } else if (parenthesesRight == ')') {
                            // 获取括号作用域
                            let currentParenthesesGroupAfterEnd = currentSqlAfter.split(')')[0]
                            let currentParenthesesSplitBeforeStart = currentSqlBefore.split('(')
                            let currentParenthesesGroupBeforeStart = ''
                            if (currentSqlBefore.match(/\(|\)/ig).splice(-3, 1) == '(') {
                                currentParenthesesGroupBeforeStart = currentParenthesesSplitBeforeStart.slice(-2).join('(')
                            } else if (currentSqlBefore.match(/\(|\)/ig).splice(-5, 1) == '(') {
                                currentParenthesesGroupBeforeStart = currentParenthesesSplitBeforeStart.slice(-3).join('(')
                            } else if (currentSqlBefore.match(/\(|\)/ig).splice(-7, 1) == '(') {
                                currentParenthesesGroupBeforeStart = currentParenthesesSplitBeforeStart.slice(-4).join('(')
                            }
                            let currentParenthesesGroupEnd = currentParenthesesGroupBeforeStart + currentParenthesesGroupAfterEnd

                            // 子查询的别名
                            let currentSubqueryAliasTem = currentParenthesesGroupEnd.match(/\)\s+[^\s+]+\,?/ig)
                            let currentSubqueryAlias = currentSubqueryAliasTem.map(v => {
                                return v.replace(/\)\s+/, '').replace(/\,/, '')
                            })
                            // 子查询的字段
                            let currentSubqueryFieldTem = currentParenthesesGroupEnd.match(/\(\s+select[\s+a-zA-Z0-9\,\.\_]+from/ig) ? currentParenthesesGroupEnd.match(/\(\s+select[\s+a-zA-Z0-9\,\.\_]+from/ig) : []
                            let currentSubqueryFieldStr = currentSubqueryFieldTem.map(v => {
                                return v.replace(/\(\s*select\s+/ig, '').replace(/\s+from/ig, '')
                            })
                            let currentSubqueryFieldNameTem = currentSubqueryFieldStr.map(v => {
                                return v.split(',').map(v => {
                                    return v.split('.')[v.split('.').length - 1]
                                })
                            })
                            let currentSubqueryFieldName = currentSubqueryAlias.map((v, i) => ({fieldName: currentSubqueryFieldNameTem[i], fieldAlia: v}))
                            // 别名和表名
                            // let currentTableNameAndTableAliaTem = currentParenthesesGroupEnd.match(/(from|\,)\s*[a-zA-Z0-9\_\s\,]*(\,|where|left|right|full|join|inner|union)/ig)
                            let currentTableNameAndTableAliaTem = currentParenthesesGroupEnd.match(/(from|\,)\s*[a-zA-Z0-9\_\s\,]*([^\s]|\,|(where|left|right|full|join|inner|union))/ig)
                            let currentTableNameAndTableAliaStr = currentTableNameAndTableAliaTem.map(v => {
                                return v.replace(/.*[\w\W]*from\s+/ig, '').replace(/\s+(where|left|right|full|join|inner|union).*/ig, '').replace(/^(\,\s*)/, '').replace(/(\s*\,)$/, '').replace(/\,\s+\(/, '').replace('(', '').replace(/[\w\W]*\.[\w\W]*/ig, '').replace(/\s*\)/ig, '')
                            })
                            let currentTableNameAndTableAliaArr = currentTableNameAndTableAliaStr.filter(v => {
                                return v && v.trim()
                            })
                            let currentTableNameAndTableAlia = []
                            currentTableNameAndTableAliaArr.map(v => {
                                v.split(/\s*\,\s*/ig).map(v => {
                                    if (v.replace(/\s+as\s+/ig, ' ').split(' ').length === 2) {
                                        currentTableNameAndTableAlia.push({
                                            tableName: v.replace(/\s+as\s+/ig, ' ').split(' ')[0],
                                            tableAlia: v.replace(/\s+as\s+/ig, ' ').split(' ')[1]
                                        })
                                    }
                                })
                            })
                            if (currentSubqueryFieldName.find(item => item.fieldAlia == strTem)) {
                                return {
                                    suggestions: currentSubqueryFieldName.find(item => item.fieldAlia == strTem).fieldName.map(v => {
                                        return {
                                            label: v,
                                            kind: monaco.languages.CompletionItemKind.Function,
                                            insertText: v,
                                            detail: '<字段>'
                                        }
                                    })
                                }
                            } else if (currentTableNameAndTableAlia.find(item => item.tableAlia == strTem)) {
                                let tablePid = ''
                                let tableName = ''
                                if (window.sessionStorage.getItem('tableName') && JSON.parse(window.sessionStorage.getItem('tableName')).length > 0) {
                                    JSON.parse(window.sessionStorage.getItem('tableName')).map(v => {
                                        if (v.label == currentTableNameAndTableAlia.find(item => item.tableAlia == strTem).tableName) {
                                            tablePid = v.pid
                                        }
                                    })
                                }
                                currentTableNameAndTableAlia.map(item => {
                                    if (item.tableAlia == strTem) {
                                        tableName = item.tableName
                                    }
                                })
                                return {
                                    suggestions: await this.getLibraryTableField(5, tablePid, tableName, this.connectName)
                                }
                            }

                        }
                    }
                }
                // 检查“点”前面的是库名还是表名，然后给出提示
                let currentPointBeforeWord = textBeforePointer.split(' ').pop().split('.').slice(-2)[0]
                // console.log(this.tableNameList)
                // console.log(this.dbNameList)
                if (this.dbNameList.find(item => item.label == currentPointBeforeWord)) {
                    return {
                        suggestions: await this.getLibraryTableField(4, tablePid, currentPointBeforeWord, this.connectName)
                    }
                } else if (this.tableNameList.find(item => item.label == currentPointBeforeWord)) {
                    return {
                        suggestions: await this.getLibraryTableField(5, tablePid, currentPointBeforeWord, this.connectName, dbName)
                    }
                } else if (textBeforePointer.trim().endsWith('.') || textBeforePointer.trim().split(' ')[textBeforePointer.trim().split(' ').length - 1].indexOf('.') > -1) {
                    return
                }
                // 默认展示内置关键字和模糊匹配结果
                return {
                    // suggestions: [...this.getKeywordSuggest(), ...await this.getLibraryTableField(0, '', strTem)]
                    suggestions: [...this.getKeywordSuggest(), ...await this.getLibraryTableField(4, dataBasePid, this.currentDbName, this.connectName), ...await this.getLibraryTableField(2)]
                }
            }
        },
        // 获取内置关键字
        getKeywordSuggest () {
            return mysqlLanguage.keywords.map(item => {
                return {
                    label: item,  // 显示的提示内容
                    kind: monaco.languages.CompletionItemKind.Keyword,  // 用来显示提示内容后的不同的图标
                    insertText: item,  // 选择后粘贴到编辑器中的文字
                    detail: '<关键字>',  // 提示内容后的说明
                    documentation: `对象名：${item}\n属性值：<关键字>`,
                }
            })
        },
        // 用来获取库名、表名、字段名
        getLibraryTableField (flag, pid, word, connName, dbName) {
            // console.log(connName)
            // if (!connName) {
            //     return this.oss.showModal({type: 'info', title: '信息提示', content: '数据库连接不可为空'});
            // }
            // 1-系统|2-库DB|3-schema|4-table|5-表字段|0-模糊匹配|6-输入任意字符联想|7-输入符号'.'联想|8-输入符号'$'联想
            if (flag == 2) {
                this.connectName = connName
                return this.Api.getDbName({ taskId: this.$route.query.id }).then(res => {//库名
                    console.log(monaco.languages.CompletionItemKind)
                    this.dbNameList = res.data.map(v => {
                        return {
                            label: v.name,
                            kind: monaco.languages.CompletionItemKind['Method'],
                            insertText: v.name,
                            detail: '<库>',
                            pid: v.id,
                            documentation: `对象名：${v.name}\n属性值：库`,
                        }
                    })
                    return this.dbNameList
                }).catch(err => {
                    console.log(err)
                })
            } else if (flag == 4) {
                // if (!word) {
                //     return this.oss.showModal({type: 'info', title: '信息提示', content: '请选择数据库'});
                // }
                return this.Api.getTableInfo({ taskId: this.$route.query.id, dbName: word }).then(res => {//表名
                    this.tableNameList = res.data.map(v => {
                        return {
                            label: v.name,
                            kind: monaco.languages.CompletionItemKind['Constant'],
                            insertText: v.name,     //选择后粘贴到编辑器中的文字
                            documentation: `对象名：${v.name}\n属性值：${word}`,
                            // detail: '<表>',
                            detail: word,
                            pid: v.id
                        }
                    })
                    return this.tableNameList
                }).catch(err => {
                    console.log(err)
                })
            } else if (flag == 5) {
                // if (!this.currentDbName) {
                //     return this.oss.showModal({type: 'info', title: '信息提示', content: '请选择数据库'});
                // }
                return this.Api.getColumnInfo({ taskId: this.$route.query.id, dbName: dbName ? dbName : this.currentDbName, tableName: word }).then(res => {
                    return res.data.map(v => {
                        return {
                            label: v.name,
                            kind: monaco.languages.CompletionItemKind['Value'],
                            insertText: v.name,
                            documentation: `对象名：${v.name}\n属性值：${dbName ? dbName : this.currentDbName}.${word}`,
                            // detail: '<字段>',
                            detail: `${dbName ? dbName : this.currentDbName}.${word}`
                        }
                    })
                }).catch(err => {
                    console.log(err)
                })
            } else if (flag == 0) {
                // return this.Api.getDbName({connName: 'ADP', current: 1, size: 10, type: flag, pid: '', word: word}).then(res => {

                //     for(let i = 0; i < res.data.length; i++) {
                //         for(let j = i + 1; j < res.data.length; j++) {
                //             if(res.data[i]['name'] === res.data[j]['name']) {
                //                 res.data.splice(j, 1)
                //                 j = j - 1
                //             }
                //         }
                //     }

                //     this.likeNameList = res.data.map(v => {
                //         return {
                //             label: v.name,
                //             kind: monaco.languages.CompletionItemKind.Keyword,
                //             insertText: v.name,
                //             detail: v.type == '1' ? '<系统>' : v.type == '2' ? '<库>' : v.type == '3' ? '<schema>' : v.type == '4' ? '<表>' : v.type == '5' ? '<字段>' : '<关键字>',
                //             pid: v.id
                //         }
                //     })
                //     return this.likeNameList
                // }).catch(err => {
                //     console.log(err)
                // })
            } else if (flag == 6) {
                // type: 1 库 | 2 表 | 5 字段
                return this.Api.getNoPointDBInfo({ taskId: this.$route.query.id, param: word }).then(res => {
                    return res.data.map(v => {
                        return {
                            label: v.name,
                            kind: monaco.languages.CompletionItemKind[`${v.type === '1' ? 'Method' : v.type === '2' ? 'Constant' : 'Value'}`],
                            insertText: v.name,
                            documentation: `对象名：${v.name}\n属性值：${v.remark ? v.remark : '<库>'}`,
                            detail: v.remark ? v.remark : '<库>'
                        }
                    })
                }).catch(err => {
                    console.log(err)
                })
            } else if (flag == 7) {
                return this.Api.getYesPointDBInfo({ taskId: this.$route.query.id, ...word }).then(res => {
                    return res.data.map(v => {
                        return {
                            label: v.name,
                            kind: monaco.languages.CompletionItemKind[`${v.type === '1' ? 'Method' : v.type === '2' ? 'Constant' : 'Value'}`],
                            insertText: v.name,
                            documentation: `对象名：${v.name}\n属性值：${v.remark ? v.remark : '<库>'}`,
                            detail: v.remark ? v.remark : '<库>'
                        }
                    })
                }).catch(err => {
                    console.log(err)
                })
            }else if(flag == 8){
                return this.Api.variableAssociation({ taskId: this.$route.query.id, str:word }).then(res => {
                    return res.data.map(v => {
                        return {
                            label: v.name,
                            kind: monaco.languages.CompletionItemKind[`Text`],
                            insertText: `${v.name.split('$')[1]}$`,
                            documentation: `对象名：${v.name}\n属性值：<变量>`,
                            detail: '<变量>'
                        }
                    })
                }).catch(err => {
                    console.log(err)
                })
            }
        },
        // 编辑器sql格式化
        formatSql () {
            this.monacoEditor.setValue(format(this.monacoEditor.getValue()))
        },
        // 获取选中的sql文本
        getSelectedSql () {
            return this.monacoEditor.getModel().getValueInRange(this.monacoEditor.getSelection())
        },
        // 获取当前任务的库名
        getCurrentDbName () {
            if(!this.isMeta){
                this.Api.setSqlBloodParams({ taskId: this.$route.query.id }).then(res => {
                    this.currentDbName = res.data.dbName
                })
            }
            
        },
        /**
         * 获取sql中所有的表名和别名
         * @param {*} sqlText SQL 字符串
         */
        getTableNameAndTableAlia(sqlText) {
            // const regTableAliaFrom = /(^|(\s+))from\s+([^\s]+(\s+|(\s+as\s+))[^\s]+(\s+|,)\s*)+(\s+(where|left|right|full|join|inner|union))?/ig
            const regTableAliaFrom = /(^|(\s+))from\s+([^\s]+(\s+|(\s+as\s+))[^\s]+(\s*|,)\s*)+(\s+(where|left|right|full|join|inner|union))?/ig
            const regTableAliaJoin = /(^|(\s+))join\s+([^\s]+)\s+(as\s+)?([^\s]+)\s+on/ig
            const regTableAliaFromList = sqlText.match(regTableAliaFrom) ? sqlText.match(regTableAliaFrom) : []
            const regTableAliaJoinList = sqlText.match(regTableAliaJoin) ? sqlText.match(regTableAliaJoin) : []
            const strList = [
                ...regTableAliaFromList.map(item => item.replace(/(^|(\s+))from\s+/ig, '').replace(/\s+(where|left|right|full|join|inner|union)((\s+.*?$)|$)/ig, '').replace(/\s+as\s+/gi, ' ').trim()),
                ...regTableAliaJoinList.map(item => item.replace(/(^|(\s+))join\s+/ig, '').replace(/\s+on((\s+.*?$)|$)/, '').replace(/\s+as\s+/gi, ' ').trim())
            ]
            const tableList = []
            strList.map(tableAndAlia => {
                tableAndAlia.split(',').forEach(item => {
                    const dbName = item.trim().split(/\s+/)[0].split('.').length > 1 ? item.trim().split(/\s+/)[0].split('.')[0] : ''
                    const tableName = item.trim().split(/\s+/)[0].split('.')[item.trim().split(/\s+/)[0].split('.').length - 1]
                    const tableAlia = item.trim().split(/\s+/)[1]
                    tableList.push(
                        {
                            dbName,
                            tableName,
                            tableAlia
                        }
                    )
                })
            })
            return tableList
        },
        searchRowNumber (lineNumber) {
            let startLineNumber = + (lineNumber.split('~').length > 1 ? lineNumber.split('~')[0] : lineNumber)
            let endLineNumber = + (lineNumber.split('~').length > 1 ? lineNumber.split('~')[1] : lineNumber)
            // this.monacoEditor.revealLine(18)
            this.monacoEditor.revealLines(startLineNumber, endLineNumber) // 跳转行数
            // let range = new monaco.Range(8, 1, 20, 1)
            // this.monacoEditor.setSelection(range)
            this.monacoEditor.setSelection({startLineNumber: startLineNumber, startColumn: 1, endLineNumber: endLineNumber, endColumn: this.monacoEditor.getModel().getLineLength(endLineNumber) + 1}) // 选中行数
            this.monacoEditor.focus()
        }
    }
}
</script>
<style lang="less">
  #monaco_edit {
    #container{
        // height:500px;
        text-align: left;
    }
    .footer {
        display: flex;
        justify-content: flex-end;
        padding-top: 20px;
    }
    
  }
  .editor-scrollable{
    left: 35px !important;
    width: calc(100% - 35px) !important;
  }
  .margin-view-overlays{
        background-color: #f8f8f8;
        border-right: 1px solid #e7e5e5;
        width: 32px !important;
  }
  .monaco-editor .line-numbers {
    color: #999 !important;
    }
  .line-numbers{
        color: #999 !important;
        min-width: 20px;
        padding: 0 3px 0 5px;
        text-align: right !important;
        white-space: nowrap;
        width: 32px !important;
    }
  .scrollbar {
     background-color: #f8f8f8 !important;
  }
  .arrow-background{
    background-color: #dcdee2;
  }
  .monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .header > .type {
        display: none;
    }
    .monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs {
        font-size: 12px;
    }
</style>
